# -*- coding: utf-8 -*-
import re
from werkzeug.utils import cached_property
from werkzeug.wrappers import Request, Response
from werkzeug.exceptions import NotFound, MethodNotAllowed
from werkzeug.contrib.securecookie import SecureCookie
from .paginator import Paginator, InvalidPage
from .helpers import get_flashed_messages, flash as _flash
from .globals import request
try:
    from simplejson import dumps
except ImportError:
    from json import dumps
SESSION_USER_KEY = '_auth_user_id'
re_page = re.compile(r'&?page=\d+')


class AccostRequest(Request):
    @property
    def kwargs(self):
        return self.environ["accost.kwargs"]

    @cached_property
    def client_session(self):
        secret_key = self.environ["accost.secret_key"]
        return SecureCookie.load_cookie(self, secret_key=secret_key)

    def flash(self, message, category="message"):
        return _flash(message, category)

    def getFlashedMessages(self, with_categories=False):
        return get_flashed_messages(with_categories)

    @cached_property
    def session(self):
        session_store = self.environ["accost.session_store"]
        sid = self.cookies.get('session_id')
        if sid is None:
            return session_store.new()
        else:
            return session_store.get(sid)

    @property
    def user_id(self):
        return self.client_session.get(SESSION_USER_KEY)

    def save_session(self, session_store, response):
        try:
            response.set_cookie('session_id', self.session.sid, max_age=3600*24*3650)
        except AttributeError:
            pass
        if self.session.should_save:
            session_store.save(self.session)

    def logout(self):
        try:
            del self.session[SESSION_USER_KEY]
        except KeyError:
            pass
        try:
            del self.client_session[SESSION_USER_KEY]
        except KeyError:
            pass

    def finish(self, response):
        session_store = self.environ["accost.session_store"]
        # save session
        self.save_session(session_store, response)
        # save client session
        self.client_session.save_cookie(response)
        self.client_session.modified = False

    def page(self, object_list, per_page, **kw):
        paginator = Paginator(object_list, per_page, **kw)
        page_num = self.args.get("page", u"1")
        if page_num == u"last":
            page_num = paginator.page_range[-1]
        try:
            page_num = paginator.validate_number(page_num)
            page = paginator.page(page_num)
        except InvalidPage:
            raise NotFound
        return page

    def url_replace(self, value, key="page"):
        value = str(value)
        match = re.search(r"[\?&]%s=[^&]*"%key, self.url)
        if match:
            repl = "".join([match.group()[0], key, "=", value])
            return re.sub(r"[\?&]%s=[^&]*"%key, repl, self.url)
        elif "?" in self.url:
            return self.url + "&%s=%s"%(key, value)
        else:
            return self.url + "?%s=%s"%(key, value)


def JsonResponse(obj):
    return Response(dumps(obj), content_type="application/json")


def error(message):
    return Response(dumps({"result": False, "message": message}),
            content_type="application/json")


def success(message, **kw):
    result = {"result": True, "message": message}
    result.update(kw)
    return Response(dumps(result), content_type="application/json")


def JsonpResponse(obj):
    key = request.args.get("callback", u"call")
    s = dumps(obj)
    return Response(key+u"("+s+u")", content_type="application/json")
